package com.groupYLP.merchant.admin.template;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;
import com.groupYLP.CouponNexus.merchant.admin.MerchantAdminApplication;
import com.groupYLP.CouponNexus.merchant.admin.dao.entity.CouponTemplateDO;
import com.groupYLP.CouponNexus.merchant.admin.dao.mapper.CouponTemplateMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

// 使用Spring Boot的测试注解，以便在测试中使用Spring Boot的功能
@SpringBootTest(classes = MerchantAdminApplication.class)
public class MockCouponTemplateDataTests {

    // 自动注入CouponTemplateMapper，用于数据库操作
    @Autowired
    private CouponTemplateMapper couponTemplateMapper;

    // 创建CouponTemplateTest实例，用于生成测试数据
    private final CouponTemplateTest couponTemplateTest = new CouponTemplateTest();

    // 创建Snowflake实例列表，用于生成唯一的商店编号
    private final List<Snowflake> snowflakes = new ArrayList<>();

    // 创建固定大小的线程池，用于并发执行任务
    private final ExecutorService executorService = new ThreadPoolExecutor(
            10,
            10,
            9999,
            TimeUnit.SECONDS,
            new SynchronousQueue<>(),
            new ThreadPoolExecutor.CallerRunsPolicy()
    );

    // 设置最大生成数量
    private final int maxNum = 500;

    /**
     * 初始化数据构建环境，为snowflakes列表添加Snowflake实例
     */
    public void beforeDataBuild() {
        for (int i = 0; i < 20; i++) {
            snowflakes.add(new Snowflake(i));
        }
    }

    /**
     * 模拟优惠券模板数据插入的测试方法
     * 初始化数据环境后，多线程并发插入数据直到达到最大数量
     */
    @Test
    public void mockCouponTemplateTest() {
        // 初始化数据环境
        beforeDataBuild();

        // 创建AtomicInteger用于线程安全的计数
        AtomicInteger count = new AtomicInteger(0);

        // 循环提交任务到线程池直到达到最大数量
        while (count.get() < maxNum) {
            executorService.execute(() -> {
                // 随机暂停一段时间，模拟并发延迟
                ThreadUtil.sleep(RandomUtil.randomInt(10));

                // 生成优惠券模板数据对象
                CouponTemplateDO couponTemplateDO = couponTemplateTest.buildCouponTemplateDO(null, new BigDecimal("10"), 1, 0, null);

                // 设置商店编号为snowflakes列表中的随机一个,调用nextId()生产一个唯一id，雪花算法
                couponTemplateDO.setShopNumber(snowflakes.get(RandomUtil.randomInt(20)).nextId());

                // 插入数据库
                couponTemplateMapper.insert(couponTemplateDO);

                // 计数器增加
                count.incrementAndGet();
            });
        }
    }
}
